<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
  <script>
    //es5 组合式继承-拿网站里的用户来举例：普通用户,vip用户，超级vip用户
    //父类-共有的，都有的属性和方法。比如用户里都有名字和密码
    function Name(name, pass) {
      this.name = name;
      this.pass = pass;
    }

    User.prototype.UserName = function () {
      console.log('父类名字', this.name);
    };
    User.prototype.UserPass = function () {
      console.log('父类密码', this.pass);
    };

    //子类
    function VipName(name, pass, level) {
      // this.name = name;
      // this.pass = pass;
      //继承公有属性？-通过改变this指向-原对象.call(指向对象参数),apply([数组]),bind() 调用
      User.call(this, name, pass)
      this.level = level;
    }
    //这样达不到面向对象的目的了
    // VipName.prototype.UserName = function () {
    //   console.log('父类名字', this.name);
    // };
    // VipName.prototype.UserPass = function () {
    //   console.log('父类密码', this.pass);
    // };

    //通过原型链继承来继承父类上的方法-把父类原型上的方法全部赋值给子类原型上
    // 1.方法1原型链继承,继承的是方法:  子类.原型=new  父类方法()
    VipName.prototype = new User()

    VipName.prototype.showLevel = function () {
      console.log('用户级别是', this.level);
    }

    let vip = new VipName('vip郑', '123456', '三级')
    vip.UserName()
    vip.UserPass()
    vip.showLevel()

    //2.拷贝继承
    /*  function VipName(name, pass, level) {
       //  this.name=name;
       // this.pass=pass;
       User.call(this, name, pass);  //构造函数里call-继承公有属性
       this.level = level;
     }
 
     VipName.prototype.showLevel = function () {
       console.log(this.level);
     }
 
     //拷贝继承- 直接赋值方法-遍历父类所有原型方法赋值给子类原型方法
     for (var i in User.prototype) {
       // console.log('父类原型方法',User.prototype);
       VipName.prototype[i] = User.prototype[i]
     }
 
     var v1 = new VipName('blue', '123456', '级别3级');
     v1.UserName();
     v1.UserPass();
     v1.showLevel(); */

    //  ex6继承
    //es6继承-先声明父类，在声明子类，通过extends继承方法,通过super()继承属性
    class Name {
      constructor(name, pass) {
        this.name = name;
        this.pass = pass;
      }

      UserName() {
        console.log(this.name);
      }
      UserPass() {
        console.log(this.pass);
      }
    }

    class VipName extends Name {
      constructor(name, pass, level) {
        super(name, pass); //继承父类上的属性  super指代了整个prototype或者__proto__指向的对象
        this.level = level;
      }
      showLevel() {
        console.log(this.level);
      }
    }
    var v1 = new VipName('blue', '123456', 3);
    v1.UserName();
    v1.UserPass();
    v1.showLevel();

    // 面向对象
    //es5面向对象-为了最大限度复用代码。面向对象也叫OOP，三大特点抽象，封装，多态
    //父类-放公共属性的，对外暴露的属性
    //比如拿tab切换来说-应该对象暴露哪些： 位置,样式
    /*   function Father(postion, type) {
        //对外暴露的属性
        this.postion1 = postion
        this.type1 = type
      }
      //构造函数原型上写逻辑方法
      Father.prototype.setPostion = function () {
        if (this.postion1 == "left") {
          //左边显示逻辑
          console.log('左边显示', this.postion1);
  
        }
        //右边显示逻辑
        if (this.postion1 == "right") {
          console.log('右边显示', this.postion1);
        }
      }
  
      Father.prototype.setStyle = function () {
  
        if (this.type1 == "border") {
          console.log('边框样式', this.type1);
        }
      }
  
      //用户在外面使用的时候,通过new 实例化，传入对应的属性
      let f1 = new Father('right', 'border')
      f1.setPostion()
      f1.setStyle() */

    //es5里  1.声明构造函数-必须大写
    /*   function User(name1, pass1) {
         //this是什么?,Object对象，通过this，在外面函数获取里面的属性值
         //  var this=new Object()
          this.name = name1;  //变量用this去定义-公有属性
          this.pass = pass1;
         //  return this;
       }
       //2.构造函数加方法——给它加User.prototype
       User.prototype.showName = function () {
         console.log(this.name);
       };
       User.prototype.showPass = function () {
         console.log(this.pass);
       };
       //3.实例化
       var u1 = new User('blue', '123456');
       u1.showName();
       u1.showPass(); */

    //es6面向对象-定义一个父类
    class User {
      constructor(name1, pass1) { //constructor构造函数
        this.name = name1; //变量用this去定义-公有属性
        this.pass = pass1;
      }

      //构造函数加方法——给它加User.prototype
      showName() {
        console.log(35, this.name);
      }
      showPass() {
        console.log(38, this.pass);
      }
    }

    var u1 = new User('blue', '123456');

    u1.showName();
    u1.showPass();
  </script>
</head>

<body>

</body>

</html>